using System;
using System.Drawing;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using Mpi.Common.Collections;
using Xeml.Document.Contracts;
using Xeml.Document;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using Mpi.Common;

namespace Xeml.Visualization.Controls
{
    partial class XemlViewer
    {
        #region Fields
        private IDocument xemlDoc;
        private int innerTopMargin = 60;
        private int innerLeftMargin = 50;
        private int innerRightMargin = 20;
        private int innerBottomMargin = 35;
        private MultiTimeLineScale mtls;
        internal VisualXemlDoc visualDoc;
        private bool mtlsEnables;
        #endregion

        #region Properties

        /// <summary>
        /// A control for a multi time line scale.
        /// </summary>
        //public MultiTimeLineScale Mtls
        //{
        //    get
        //    {
        //        return this.mtls;
        //    }
        //    set
        //    {
        //        //this.mtls = value;
        //        //if (this.mtls != null)
        //        //{
        //        //    this.mtls.EditTimeChanged += new EventHandler<TimeChangeEventArgs>(OnEditTimeChanged);
        //        //    this.mtls.EditTimeChanging += new EventHandler<TimeChangeEventArgs>(OnEditTimeChanging);
        //        //}
        //        //SetupMtls();
        //    }
        //}



        /// <summary>
        /// Indicates whether or not the timline scale control is enabled or not.
        /// </summary>
        public bool MtlsEnabled
        {
            get { return this.mtls != null; }
            //set
            //{
            //    mtlsEnables = value;
            //    SetupMtls();
            //}
        }


        /// <summary>
        /// The height for each story.
        /// </summary>
        public int StoryAreaHeight
        {
            get { return this.visualDoc.StoryAreaHeight; }
            set
            {
                if (this.xemlDoc != null)
                    this.visualDoc.StoryAreaHeight = value;
                Invalidate();
            }
        }

        /// <summary>
        /// The document which will be rendered through this control.
        /// </summary>
        public IDocument XemlDoc
        {
            get { return xemlDoc; }
            set
            {
                xemlDoc = value;
                this.visualDoc.XemlDoc = value;

                if (xemlDoc != null)
                {
                    xemlDoc.Changed += new EventHandler(xemlDoc_Changed);
                    xemlDoc.Loaded += new EventHandler(xemlDoc_Loaded);
                    //InitTimeScale();
                    //SetupPositions();
                }
                SetupMtls();
                Invalidate();
            }
        }

        void xemlDoc_Changed(object sender, EventArgs e)
        {
            Invalidate();
        }

        public TimeRegionPixelMapper PxMapper
        {
            get
            {
                return this.visualDoc.PxMapper;
            }
        }



        // private List<ObservationPoint> selectedObPoints;
        public ObservationPoint[] SelectedObservationPoints
        {
            get
            {
                List<ObservationPoint> temp = new List<ObservationPoint>();
                foreach (VisObserverPoint vop in this.visualDoc.SelectedOpPoints)
                {
                    temp.Add(vop.ObservationPoint);
                }
                return temp.ToArray();
            }
        }

        public ObservationPoint SelectedObservationPoint
        {
            get
            {
                if (visualDoc.SelectedObPoint == null)
                    return null;
                else
                    return visualDoc.SelectedObPoint.ObservationPoint;
            }
        }

        public Event SelectedEvent
        {
            get
            {
                if (visualDoc.SelectedEvent == null)
                    return null;
                else
                    return visualDoc.SelectedEvent.Event;
            }
        }



        // private List<TreeNode<StoryBase>> selectedStoryBases;
        public TreeNode<StoryBase>[] SelectedStoryBases
        {
            get
            {
                // return selectedStoryBases;
                List<TreeNode<StoryBase>> temp = new List<TreeNode<StoryBase>>();
                foreach (VisStory vs in this.visualDoc.SelectedStories)
                {
                    temp.Add(vs.Story);
                }
                return temp.ToArray();
            }
        }

        public TreeNode<StoryBase> SelectedStoryBase
        {
            get
            {
                if (this.visualDoc.SelectedStory == null)
                    return null;
                else
                    return this.visualDoc.SelectedStory.Story;
            }
        }


        public VisualDocElement MostTopSelectedElement
        {
            get { return visualDoc.MostTopSelectedElement; }
        }





        #endregion

        #region Methods
        /// <summary>
        /// Setup the multi timeline scale control.
        /// </summary>
        private void SetupMtls()
        {
            if (this.mtls == null)
            {
                this.mtls = new MultiTimeLineScale();

                mtls.RowHeaderWidth = this.innerLeftMargin;
                this.mtls.DeactivateTimeEditor(true);
                mtls.Location = new Point(0, 0);
                mtls.MinimumSize = new Size(10, 0);
                mtls.Dock = DockStyle.Top;
                mtls.Height = 0;
               // this.Controls.Add(mtls);
                mtls.BringToFront();
                mtls.EditTimeChanged += new EventHandler<TimeChangeEventArgs>(OnEditTimeChanged);
                mtls.EditTimeChanging += new EventHandler<TimeChangeEventArgs>(OnEditTimeChanging);
            }
            if (this.xemlDoc != null)
                mtls.Setup(this.visualDoc.PxMapper);
            else
                mtls.Setup(null);
           

            //if (this.visualDoc.XemlDoc != null && MtlsEnabled)
            //{

            //    this.innerLeftMargin = mtls.RowHeaderWidth + mtls.Left;
            //    this.mtls.DeactivateTimeEditor();
            //    this.mtls.Setup(this.visualDoc.PxMapper);


            //}
            //else if (this.xemlDoc == null && MtlsEnabled)
            //{
            //    this.mtls.Setup(null);
            //}

        }



        /// <summary>
        /// Initializes the multi timline scale based up the current xeml document.
        /// </summary>
        //private void InitTimeScale()
        //{
        //    visualDoc.PxMapper.Regions.Clear();
        //    if (this.xemlDoc == null)
        //        return;
        //    List<TimeSpan> temp = new List<TimeSpan>();

        //    foreach (TreeNode<StoryBase> sb in this.xemlDoc.StoryBoard)
        //    {
        //        TimeRegion tr = new TimeRegion();
        //        if (sb.Content is StorySplit)
        //        {
        //            if (!temp.Contains((sb.Content as StorySplit).Time))
        //                temp.Add((sb.Content as StorySplit).Time);
        //        }
        //    }
        //    if (!temp.Contains(xemlDoc.ObserverTime))
        //        temp.Add(xemlDoc.ObserverTime);

        //    temp.Sort();
        //    TimeSpan t1 = TimeSpan.Zero;
        //    TimeSpan t2 = TimeSpan.Zero;

        //    for (int i = 0; i < temp.Count; i++)
        //    {
        //        //TODO: use this call
        //       // visualDoc.PxMapper.SplitRegion(temp[i]);

        //        t2 = temp[i];
        //        if (i > 0)
        //            t1 = temp[i - 1];
        //        TimeRegion tr = new TimeRegion();
        //        tr.Length = t2 - t1;
        //        tr.Resolution = 1;
        //        visualDoc.PxMapper.Regions.AddLast(tr);

        //    }

        //    //if(mtls != null)
        //    //    mtls.Setup(visualDoc.PxMapper);

        //}

        /// <summary>
        /// Setups all positions for the document rendering.
        /// </summary>
        //        private void SetupPositions()
        //        {
        ////            CalculateDrawAreaX();
        //            if (mtls != null)
        //            {
        //               // mtls.Left = this.drawAreaOrigin - mtls.RowHeaderWidth;
        //               // mtls.Top = (int)(innerTopMargin + visualDoc.DrawArea.Height + 10f);
        //            }

        //        }

        ///// <summary>
        ///// Calculates the draw area for the current document.
        ///// </summary>
        //private void CalculateDrawAreaX()
        //{
        //     drawAreaOrigin = this.innerLeftMargin;
        //}


        /// <summary>
        /// Do all required steps after a document change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// 
        // private void xemlDoc_CodeChanged(object sender, EventArgs e)
        //{
        //    //this.visualDoc.ResetDocument();
        //    //InitTimeScale(); //zu viel des Guten
        //    //this.SetupMtls(); //zu viel des Guten
        //    //SetupPositions();

        //    //this.AdjustSize();
        //    //Invalidate();
        //}

        void xemlDoc_Loaded(object sender, EventArgs e)
        {
            this.visualDoc.ResetDocument();
        }


        /// <summary>
        /// Calculates the required size of this control.
        /// </summary>
        private void AdjustSize()
        {
            RectangleF da = this.visualDoc.DrawArea;
            //this.AutoScrollMinSize = new Size(((int)da.Width + 2 * innerLeftMargin), ((int)da.Height + innerTopMargin + innerBottomMargin));
            //if(mtls != null)
            this.AutoScrollMinSize = new Size((int)this.visualDoc.DrawArea.Width + innerLeftMargin + innerRightMargin, (int)this.visualDoc.DrawArea.Height + innerTopMargin + innerBottomMargin);



        }

        #endregion

        private bool timeEditPreviewMode = false;
        private Rectangle timeEditPreviewInvalidation;
        private int timeEditPreviewXOffSet = 0;

        void OnEditTimeChanged(object sender, TimeChangeEventArgs e)
        {
            Debug.WriteLine("XemlViewer: ......change time......");
            timeEditPreviewMode = false;
            timeEditPreviewXOffSet = 0;


            if (visualDoc.MostTopSelectedElement == VisualDocElement.ObservationPoint)
            {
                Debug.WriteLine("XemlViewer: change Time for ObPpoint");
                ObservationPoint op = e.TimeObject as ObservationPoint;
                //op.Time = e.NewTime;

              foreach (VisObserverPoint vop in visualDoc.SelectedOpPoints)
                {
                    vop.ObservationPoint.TimePoint += e.Diff; 
               }
            }
            else if (visualDoc.MostTopSelectedElement == VisualDocElement.SplitDot || visualDoc.MostTopSelectedElement == VisualDocElement.Story)
            {
                Debug.WriteLine("XemlViewer: change Time for SplitDot");
                StorySplit ss = e.TimeObject as StorySplit;
                ss.TimePoint = e.NewTime;
            }
            else if (visualDoc.MostTopSelectedElement == VisualDocElement.Event)
            {
                Debug.WriteLine("XemlViewer: change Time for SplitDot");
                Event ev = e.TimeObject as Event;
                ev.TimePoint = e.NewTime;
            }

            //if (visualDoc.SelectedOpPoints.Length > 1)
            //{
            //    foreach (VisObserverPoint vop in visualDoc.SelectedOpPoints)
            //    {
            //        vop.ObservationPoint.Time += e.Diff; 
            //    }
            //}
            //else
            //{
            //    foreach (VisObserverPoint vop in visualDoc.SelectedOpPoints)
            //    {
            //        vop.ObservationPoint.Time = e.NewTime;
            //    }
            //}
            //this.visualDoc.ResetDocument();



        }

        void OnEditTimeChanging(object sender, TimeChangeEventArgs e)
        {

            if (!timeEditPreviewMode)
            {
                Debug.WriteLine("XemlViewer: Changing time" + e.OldTime.ToString() + "->" + e.NewTime.ToString());
                timeEditPreviewMode = true;
                Rectangle b = default(Rectangle);
                if (visualDoc.MostTopSelectedElement == VisualDocElement.ObservationPoint)
                {
                    Debug.WriteLine("XemlViewer: TopMost is ObservationPoint");
                    b = Rectangle.Round(visualDoc.SelectedObPoint.Bounds);
                }
                else if (visualDoc.MostTopSelectedElement == VisualDocElement.SplitDot || visualDoc.MostTopSelectedElement == VisualDocElement.Story)
                {
                    Debug.WriteLine("XemlViewer: TopMost is SplitDot");
                    b = Rectangle.Round(visualDoc.SelectedSplitDot.Bounds);
                }
                else if (visualDoc.MostTopSelectedElement == VisualDocElement.Event)
                {
                    Debug.WriteLine("XemlViewer: TopMost is Event");
                    b = Rectangle.Round(visualDoc.SelectedEvent.Bounds);
                }
                this.timeEditPreviewInvalidation = new Rectangle();
                this.timeEditPreviewInvalidation.X = 0;
                this.timeEditPreviewInvalidation.Y = b.Top + innerTopMargin - 2;
                this.timeEditPreviewInvalidation.Width = this.Width;
                this.timeEditPreviewInvalidation.Height = b.Height + 4;
               // this.Invalidate();
            }


            int x0 = visualDoc.PxMapper.MapPoint(e.OldTime);
            int x1 = visualDoc.PxMapper.MapPoint(e.NewTime);

            Debug.Write("XemlViewer: Mappe OldTimeZuPixel: ");
            Debug.WriteLine(e.OldTime.ToString() + "_zu_" + x0);
            Debug.Write("XemlViewer: Mappe NewTimeZuPixel: ");
            Debug.WriteLine(e.NewTime.ToString() + "_zu_" + x1);
            Debug.WriteLine("XemlViewer: TimeEditOffset ist " + (x1 - x0));
            this.timeEditPreviewXOffSet = x1 - x0;
            //Rectangle inv = new Rectangle();
            //Rectangle b = Rectangle.Round(visualDoc.SelectedObPoint.Triangel.GetBounds());
            //inv.X = Math.Min(b.X + innerLeftMargin, x1);
            //inv.Y = b.Y + innerTopMargin;
            //inv.Height = b.Height;
            //inv.Width = Math.Max(b.Right + innerLeftMargin, x1);

            //if (activeHotSpot < 0)
            //{
            //    if (visualDoc.HotSpots.Contains(x1))
            //    {
            //        activeHotSpot = x1;
            //        Invalidate();
            //    }
            //    else
            //    {
            //        activeHotSpot = -1;
            //        Invalidate(this.timeEditPreviewInvalidation);
            //    }
            //}
            //else
            //{
            //    if (!visualDoc.HotSpots.Contains(x1))
            //    {
            //        activeHotSpot = -1;
            //        Invalidate();
            //    }
            //    else
            //    {
                   
            //        Invalidate(this.timeEditPreviewInvalidation);
            //    }
            //}

            Invalidate(this.timeEditPreviewInvalidation);
            OnTimeEditPreviewChange(e.OldTime, e.NewTime);
            //    Invalidate();
        }


        public event EventHandler<PropertyHasChangedEventArgs<TimeSpan>> TimeEditPreviewChange;
        protected virtual void OnTimeEditPreviewChange(TimeSpan oldVal, TimeSpan newVal)
        {
            if (TimeEditPreviewChange != null)
            {
                TimeEditPreviewChange(this, new PropertyHasChangedEventArgs<TimeSpan>(oldVal, newVal));
            }
        }

    }
}
